import { ref, computed } from "vue";
import type { Ref, ExtractPropTypes } from "vue";
import type {
  Column,
  Columns,
  DataIndex,
  WithTableSignal,
  SetTableDataConfig,
  State,
} from "./types";

export function useTableData<T>() {
  const data: Ref<WithTableSignal<T>[]> = ref([]);

  /**
   * 返回（删除__id__，非ref）数据
   */
  function getTableData() {
    const nakedData = data.value.map((item) => {
      const { __id__, __state__, ...newItem } = item;
      return newItem;
    });

    return nakedData as T[];
  }

  /**
   * 初始化或重新设置表格数据，返回一个ref值
   */
  function setTableData(
    newVal: T[],
    config?: SetTableDataConfig
  ): Ref<WithTableSignal<T>[]> {
    const copy = jsonCopy(newVal) as T[];
    const newValWithId = copy.map((item) => withTableSignal(item, config));
    data.value = newValWithId;
    // WithTableSignal<T>[]' is not assignable to type
    // WithTableSignal<T>[]'. Two different types with this name exist, but they are
    return data;
  }

  /**
   * 添加一行或多行
   */
  function add(...items: T[] | number[]) {
    const newItems = items.map((itemOrIndex) => {
      if (typeof itemOrIndex === "number") {
        return addByIndex(itemOrIndex);
      }
      return withTableSignal(itemOrIndex);
    });
    // console.log("🚀 ~ newItems ~ newItems:", newItems);

    data.value.push(...(newItems as WithTableSignal<T>[]));
  }

  function addByIndex(index: number) {
    const newItem = jsonCopy(data.value[index]);

    for (const key in newItem) {
      if (Object.prototype.hasOwnProperty.call(newItem, key)) {
        const value = newItem[key];

        if (typeof value === "number") {
          newItem[key] = 0;
        } else if (typeof value === "boolean") {
          newItem[key] = false;
        } else {
          newItem[key] = "";
        }
      }
    }

    return withTableSignal(newItem);
  }

  /**
   * 根据id或者数组索引删除一行
   */
  function remove(indexOrId: number | string) {
    if (typeof indexOrId === "number") {
      removeByIndex(indexOrId);
    } else {
      removeById(indexOrId);
    }
  }

  function removeByIndex(index: number) {
    data.value = data.value.filter((_, idx) => idx !== index);
    // console.log("🚀 ~ removeByIndex ~  data.value:", data.value);
  }

  function removeById(id: string) {
    data.value = data.value.filter((item) => item.__id__ !== id);
  }

  /**
   * 根据id或者数组索引复制一行
   */
  function copy(indexOrId: number | string) {
    if (typeof indexOrId === "string") {
      copyById(indexOrId);
    } else {
      copyByIndex(indexOrId);
    }
  }

  function copyByIndex(index: number) {
    const item = data.value[index];
    if (item) {
      const copyItem = withTableSignal(jsonCopy(item));
      data.value.splice(index + 1, 0, copyItem);
    }
  }

  function copyById(id: string) {
    const index = data.value.findIndex((e) => e.__id__ === id);
    if (index > -1) {
      copyByIndex(index);
    }
  }

  // 设置__state__根据__id__或index
  function setState(indexOrId: string | number, state: State) {
    if (typeof indexOrId === "string") {
      setStateById(indexOrId, state);
    } else {
      setStateByIndex(indexOrId, state);
    }
  }

  function setStateByIndex(index: number, state: State) {
    data.value[index].__state__ = state;
  }

  function setStateById(id: string, state: State) {
    const index = data.value.findIndex((item) => item.__id__ === id);
    if (index >= 0) setStateByIndex(index, state);
  }

  // 设置所有__state__
  function setAllState(state: State) {
    data.value.forEach((item) => (item.__state__ = state));
  }

  function jsonCopy<T extends object>(obj: T) {
    return JSON.parse(JSON.stringify(obj));
  }

  function withTableSignal<T>(
    rowData: T,
    config: SetTableDataConfig = {
      __state__: "edit",
    }
  ): WithTableSignal<T> {
    return Object.assign(rowData as any, {
      __id__: crypto.randomUUID(),
      __state__: config.__state__ ?? "edit",
    });
  }

  return {
    getTableData,
    setTableData,

    add,
    copy,
    remove,

    setState,
    setAllState,
  };
}
